/*
 * Copyright (c) 2011 Robert Kirchgessner <rkirchge@gmail.com>
 *                    Carlo Pascoe <carlo.pascoe@gmail.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
#include <time.h>
#include <math.h>
#include <sys/time.h>

#include "debug.h"
#include "graph.h"
#include "subgraphoverlay.h"
#include "hashgraph.h"
#include "motifsearch.h"
#include "randgraph.h"

#define feature_size 3
#define group_size 2
#define RAND 10
#define Threshold 1

double timerval()
{
    struct timeval st;
    gettimeofday(&st, NULL);
    return (st.tv_sec + st.tv_usec*1e-6);
}

int
main(int argc, char *argv[])
{
    struct graph g;
    struct graph rg;
    struct overlaygraph og;
    double start_time, end_time;

    srand(time(NULL));
    graph_init(&g);

    printf("Loading graph...");
    fflush(stdout);
    start_time = timerval();
    graph_from_file(argv[1], &g);
    end_time = timerval();
    printf("Complete (%lf s)\n", end_time-start_time);

    //graph_write_dotty("test.dot", &g);
    printf("Graph loaded! Size: %d\n", g.size);
    overlay_init(&og);

    printf("Generating subgraph overlay feature size=%d...", feature_size);
    fflush(stdout);
    start_time = timerval();
    generate_subgraph_overlay(&g, &og, METHOD_DEGREE_PRIORITY, feature_size);
    end_time = timerval();
    printf("Complete (%lf s)\n", end_time-start_time);

    //overlay_print(&og);
    overlay_write_dotty("dotty.dot", &og);

    struct hash_graph hg;
    hash_init(&hg, &og, hash_func, feature_size);
    //print_int_mat((int *)hg.hash_adj, (int)hg.size);

    struct graph candidate_motif;
    struct overlaygraph candidate_overlay;
    struct hash_graph overlay_hg;
    struct motif_list_head motif_list;
    FILE *gfp = fopen("motifs.g6", "r");
    char g6str[10];
    int mcnt, i, j, k;

    mcnt = -1;
    while(!feof(gfp)){
      mcnt++;
      fscanf(gfp, "%10s", g6str);
    }


    double *mean_inrand = (double *)malloc(mcnt*sizeof(double));
    memset(mean_inrand, 0, mcnt*sizeof(double));
    double *var_inrand = (double *)malloc(mcnt*sizeof(double));
    memset(var_inrand, 0, mcnt*sizeof(double));
    double *total_inreal = (double *)malloc(mcnt*sizeof(double));
    memset(total_inreal, 0, mcnt*sizeof(double));

    rewind(gfp);
    fscanf(gfp, "%10s", g6str);
    k = 0;
  
    //For each candidate motif, we perform a hash alignment and store the count result
    while(!feof(gfp)){
      graph_init(&candidate_motif);
      motif_template_generate(g6str, NULL, &candidate_motif);
      overlay_init(&candidate_overlay);
      generate_subgraph_overlay(&candidate_motif, &candidate_overlay, METHOD_DEGREE_PRIORITY, feature_size);
      //overlay_write_dotty("overlay.dot", &candidate_overlay);
      hash_init(&overlay_hg, &candidate_overlay, hash_func, feature_size);
      motif_align(&hg, &overlay_hg, &motif_list, Threshold, feature_size);
      printf("I GOT %d MOTIFS!\n", motif_list.list_cnt);
      total_inreal[k] = (double)motif_list.list_cnt;
      free_motif_list(&motif_list);
      hash_cleanup(&overlay_hg);
      overlay_cleanup(&candidate_overlay);
      graph_cleanup(&candidate_motif);

      fscanf(gfp, "%10s", g6str);
      k++;
    }

    hash_cleanup(&hg);
    overlay_cleanup(&og);

    for(k = 0; k < RAND; k++){
      graph_init(&rg);

      printf("generating random graph...");
      fflush(stdout);
      start_time = timerval();
      i = (int)markov_rand_graph(&g, NULL, &rg, 10);
      end_time = timerval();
      printf("Complete (%lf s) ...... returned %d\n", end_time-start_time, i);
      overlay_init(&og);

      printf("Generating subgraph overlay feature size=%d...", feature_size);
      fflush(stdout);
      start_time = timerval();
      generate_subgraph_overlay(&rg, &og, METHOD_DEGREE_PRIORITY, feature_size);
      end_time = timerval();
      printf("Complete (%lf s)\n", end_time-start_time);

      hash_init(&hg, &og, hash_func, feature_size);

      rewind(gfp);
      fscanf(gfp, "%10s", g6str);
      j = 0;
      while(!feof(gfp)){
        graph_init(&candidate_motif);
        motif_template_generate(g6str, NULL, &candidate_motif);
        overlay_init(&candidate_overlay);
        generate_subgraph_overlay(&candidate_motif, &candidate_overlay, METHOD_DEGREE_PRIORITY, feature_size);
        //overlay_write_dotty("overlay.dot", &candidate_overlay);
        hash_init(&overlay_hg, &candidate_overlay, hash_func, feature_size);
        motif_align(&hg, &overlay_hg, &motif_list, Threshold, feature_size);
        printf("I GOT %d MOTIFS!\n", motif_list.list_cnt);

        mean_inrand[j] += (double)motif_list.list_cnt;
        var_inrand[j] += (double)motif_list.list_cnt*motif_list.list_cnt;

        free_motif_list(&motif_list);
        hash_cleanup(&overlay_hg);
        overlay_cleanup(&candidate_overlay);
        graph_cleanup(&candidate_motif);
        fscanf(gfp, "%10s", g6str);
        j++;
     }
     hash_cleanup(&hg);
     overlay_cleanup(&og);
     graph_cleanup(&rg);
  }

  fclose(gfp);

  int subcnt = 0;
  printf("\n\n\ntotal = ");
  for(j = 0; j <  mcnt; j++){
    subcnt += total_inreal[j];
    printf("%f\t",(double)total_inreal[j]);
  }
  printf("\nmean = ");
  for(j = 0; j <  mcnt; j++){
    printf("%f\t",(double)mean_inrand[j]);
  }
  printf("\nvar = ");
  for(j = 0; j <  mcnt; j++){
    printf("%f\t",(double)var_inrand[j]);
  }
  printf("\n\n\n%d\n",mcnt);
  
  calculateZSCORE(subcnt, RAND, mcnt, mean_inrand, var_inrand, total_inreal, "./") ;

  //graph_write_dotty("test.dot", &g);
  graph_cleanup(&g);
  free(mean_inrand);
  free(var_inrand);
  free(total_inreal);
  return 0;
}

